package com.whpost.service.wx.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.whpost.service.entity.t.TRegion;
import com.whpost.service.entity.t.TXzjg;
import com.whpost.service.entity.tools.ResultInfo;
import com.whpost.service.service.WxBaseServices;
import com.whpost.service.tools.ToolBean;
import com.whpost.service.wx.dao.WxBaomingMapper;
import com.whpost.service.wx.entiy.*;
import jakarta.annotation.Resource;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutNewsMessage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class WechatJsService extends WxBaseServices<WxBaomingMapper, WxBaoming> {

    @Resource
    private WxMpService wxMpService;

    public ResultInfo getWxJsConfig(String loginId, Map<String, Object> map) {

        ToolBean.info("准备获取WXJS配置>>>开始");

        // 1. 校验用户信息
        if (StringUtils.isEmpty(loginId)) {
            return new ResultInfo(500, "用户信息丢失！", null);
        }

        try {
            // 2. 解析请求参数（确保jsonObject正确转换）
            JSONObject jsonObject = getData(map, loginId);

            ToolBean.info("准备获取WXJS配置>>>WxJsApiRequest准备中："+jsonObject.toJSONString());

            WxJsApiRequest request = JSON.parseObject(jsonObject.toJSONString(), WxJsApiRequest.class);

            // 3. 校验URL参数
            if (request.getUrl() == null || request.getUrl().trim().isEmpty()) {
                return new ResultInfo(500, "URL不能为空！", null);
            }

            // 4. 调用微信接口获取jsapi_ticket（可能抛出WxErrorException）
            String jsapiTicket;
            try {
                jsapiTicket = wxMpService.getJsapiTicket();
            } catch (WxErrorException e) {
                ToolBean.info("准备获取WXJS配置>>>获取jsapiTicket发生错误！["+e.getError().getErrorCode()+"]["+e.getError().getErrorMsg()+"]");
                // 捕获微信接口错误，提取错误码和信息
                String errorMsg = String.format(
                        "微信接口错误：%s（错误码：%d）",
                        e.getError().getErrorMsg(),
                        e.getError().getErrorCode()
                );
                // 打印详细日志（便于排查）
                e.printStackTrace();
                // 返回包含微信错误信息的响应
                return new ResultInfo(500, errorMsg, null);
            }

            // 5. 生成签名相关参数
            String nonceStr = generateNonceStr();
            String signature = generateSignature(jsapiTicket, nonceStr, request.getTimestamp(), request.getUrl());

            ToolBean.info("准备获取WXJS配置>>>jsapiTicket："+jsapiTicket);
            ToolBean.info("准备获取WXJS配置>>>nonceStr："+nonceStr);
            ToolBean.info("准备获取WXJS配置>>>timestamp："+request.getTimestamp());
            ToolBean.info("准备获取WXJS配置>>>url："+request.getUrl());


            // 6. 构建成功响应
            WxJsApiResponse response = new WxJsApiResponse();
            response.setAppId(wxMpService.getWxMpConfigStorage().getAppId());
            response.setTimestamp(request.getTimestamp());
            response.setNonceStr(nonceStr);
            response.setSignature(signature);

            ToolBean.info("准备获取WXJS配置>>>获取到的："+response.toString());

            return backRtn(new ResultInfo(200, "成功返回！", response), loginId);

        } catch (Exception e) {
            // 处理其他非微信接口异常（如参数解析错误）
            ToolBean.info("准备获取WXJS配置>>>生成微信签名失败："+e.getMessage());
            return backRtn(new ResultInfo(500, "生成微信签名失败：" + e.getMessage(), null), loginId);
        }
    }

    /**
     * 生成微信JSSDK签名
     * 规则：jsapi_ticket=XXX&noncestr=XXX×tamp=XXX&url=XXX → SHA1加密
     */
    private String generateSignature(String jsapiTicket, String nonceStr, Long timestamp, String url) throws Exception {
        String signatureStr = String.format(
                "jsapi_ticket=%s&noncestr=%s&timestamp=%d&url=%s",
                jsapiTicket, nonceStr, timestamp, url
        );
        // SHA1加密
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        byte[] digest = md.digest(signatureStr.getBytes(StandardCharsets.UTF_8));
        // 转换为十六进制字符串
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    /**
     * 生成随机字符串（noncestr）
     */
    private String generateNonceStr() {
        String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        SecureRandom random = new SecureRandom();
        StringBuilder sb = new StringBuilder(16);
        for (int i = 0; i < 16; i++) {
            sb.append(chars.charAt(random.nextInt(chars.length())));
        }
        return sb.toString();
    }

    /**
     * AES解密（与前端保持一致：CBC模式，PKCS5Padding填充）
     */
    private String aesDecrypt(String encryptedData, String key, String iv) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
        return new String(decrypted, StandardCharsets.UTF_8);
    }

    /**
     * AES加密（与前端保持一致：CBC模式，PKCS5Padding填充）
     */
    private String aesEncrypt(String data, String key, String iv) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
        byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

}
